package com.hzy.app.utils;

import com.hzy.context.ApplicationContext;
import com.hzy.context.ApplicationContextUtils;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.mysqlclient.MySQLConnectOptions;
import io.vertx.mysqlclient.MySQLPool;
import io.vertx.sqlclient.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author huangzhenyu
 * @date 2024/9/10 23:03
 */
public class DbUtils {

    private static final Logger log = LoggerFactory.getLogger(DbUtils.class);

    protected static Pool client = null;
    static final ApplicationContext applicationContext = ApplicationContextUtils.getRequiredApplicationContext();


    public static void initializer(Vertx vertx) {
        registerDbPool(vertx);
        QueryUtil.registerConverters();
    }

    private static void registerDbPool(Vertx vertx) {
        Integer port = applicationContext.getProperty("app.db.mysql.port", Integer.class, 3306);
        String host = applicationContext.getProperty("app.db.mysql.host", String.class, "127.0.0.1");
        String database = applicationContext.getProperty("app.db.mysql.database", String.class, "test");
        String user = applicationContext.getProperty("app.db.mysql.username", String.class, "root");
        String password = applicationContext.getProperty("app.db.mysql.password", String.class, "");
        Integer pipeliningLimit = applicationContext.getProperty("app.db.mysql.pipeliningLimit", Integer.class, 16);

        log.debug("[mysql] Connecting to database with settings: host={}, port={}, database={}, username={}, pipeliningLimit={}", host, port, database, user, pipeliningLimit);

        MySQLConnectOptions connectOptions = new MySQLConnectOptions()
                .setPort(port)
                .setHost(host)
                .setDatabase(database)
                .setUser(user)
                .setPassword(password)
                .setPipeliningLimit(pipeliningLimit);

        PoolOptions poolOptions = new PoolOptions()
                .setMaxSize(applicationContext.getProperty("app.db.mysql.pool.maxSize", Integer.class, 8));

        client = MySQLPool.pool(vertx, connectOptions, poolOptions);
    }


    public static Pool getClient() {
        return client;
    }

    public static Future<SqlConnection> getConnection() {
        return client.getConnection();
    }

    /**
     * 查询数据并将结果映射为实体列表
     *
     * @param sql   查询 SQL 语句
     * @param clazz 实体类的 Class 对象
     * @param <T>   实体类类型
     * @return 包含实体列表的 Future
     */
    public static <T> Future<List<T>> query(String sql, Class<T> clazz) {
        return QueryUtil.query(sql, Tuple.tuple(), clazz);
    }

    /**
     * 查询数据并将结果映射为实体列表
     *
     * @param sql    查询 SQL 语句
     * @param params 查询参数
     * @param clazz  实体类的 Class 对象
     * @param <T>    实体类类型
     * @return 包含实体列表的 Future
     */
    public static <T> Future<List<T>> query(String sql, List<?> params, Class<T> clazz) {
        return QueryUtil.query(sql, Tuple.from(params), clazz);
    }

    /**
     * 查询数据并将结果映射为实体列表
     *
     * @param sql    查询 SQL 语句
     * @param params 查询参数
     * @param clazz  实体类的 Class 对象
     * @param <T>    实体类类型
     * @return 包含实体列表的 Future
     */
    public static <T> Future<List<T>> query(String sql, Tuple params, Class<T> clazz) {
        return QueryUtil.query(sql, params, clazz);
    }

    /**
     * 插入数据
     *
     * @param sql 插入 SQL 语句
     * @return 包含插入结果的 Future
     */
    public static Future<RowSet<Row>> insert(String sql) {
        return client.query(sql).execute();
    }

    /**
     * 插入数据
     *
     * @param sql    插入 SQL 语句
     * @param params 插入参数
     * @return 包含插入结果的 Future
     */
    public static Future<RowSet<Row>> insert(String sql, Tuple params) {
        return client.preparedQuery(sql).execute(params);
    }


    /**
     * 更新数据
     *
     * @param sql 更新 SQL 语句
     * @return 包含更新结果的 Future
     */
    public static Future<RowSet<Row>> update(String sql) {
        return client.preparedQuery(sql).execute();
    }

    /**
     * 更新数据
     *
     * @param sql    更新 SQL 语句
     * @param params 更新参数
     * @return 包含更新结果的 Future
     */
    public static Future<RowSet<Row>> update(String sql, Tuple params) {
        return client.preparedQuery(sql).execute(params);
    }

    /**
     * 删除数据
     *
     * @param sql 删除 SQL 语句
     * @return 包含删除结果的 Future
     */
    public static Future<RowSet<Row>> delete(String sql) {
        return client.preparedQuery(sql).execute();
    }

    /**
     * 删除数据
     *
     * @param sql    删除 SQL 语句
     * @param params 删除参数
     * @return 包含删除结果的 Future
     */
    public static Future<RowSet<Row>> delete(String sql, Tuple params) {
        return client.preparedQuery(sql).execute(params);
    }



}
